<template>
  <div class="wrapper">
    <xdh-curd
      name="formItemList"
      :model="form"
      :mixin="mixin"
      :filter="false"
      :pager="pager"
      modelKey="pkValue"
      :query="id"
      :rules="formRules"
      :pageSize="pageSize"
      dialog-width="800px"
      formLabelWidth="130px"
      dialogWidth="90%"
      dialogHeight="90%"
      :handleType="'icon'"
      @on-dialog-open="handleDialogOpen"
      :insertHandler="insertHandler"
      :updateHandler="updateHandler"
      ref="formItemList"
      listTitle="表单项"
    >
      <!-- 数据列表 -->
      <template slot="table-columns" slot-scope="scope">
        <el-table-column label="名称" prop="label"></el-table-column>
        <el-table-column label="类型" prop="type"></el-table-column>
      </template>

      <template slot="table-tool">
        <el-button size="mini" @click="view" plain>预览表单</el-button>
        <el-button size="mini" type="danger" @click="createHtml" plain>生成表单</el-button>
        <el-switch
          v-model="isSortTable"
          active-text="是否开启拖拉排序"
          @change="sortTableChange">
        </el-switch>
        <el-button size="mini" @click="saveSortTable" v-show="isSortTable" plain>保存修改</el-button>
        <el-button size="mini" @click="$router.back()" type="warning" plain>返回列表</el-button>
      </template>

      <!-- 新增/修改弹窗 -->
      <template slot="dialog-form-items" slot-scope="prop">
        <el-form-item prop="type" label="类型">
          <el-select v-model="prop.model.type" placeholder="请选择类型" @change="selectChange(prop)">
            <el-option v-for="(list,index) in typeData" :key="index" :label="list.name" :value="list.value"></el-option>
          </el-select>
          <el-checkbox-group v-model="prop.model.isBranches" v-show="prop.model.type === 'select'" class="inline-input"
                             @change="isBranchesChange">
            <el-checkbox name="isBranches" v-for="(item,index) in isBranches" :key="index"
                         :label="item.value">{{item.name}}
            </el-checkbox>
          </el-checkbox-group>
        </el-form-item>
        <el-form-item label="名称" v-show="prop.model.type === 'dynamic' || prop.model.isBranches.length">
          <el-input v-model="prop.model.label"></el-input>
        </el-form-item>
        <div v-for="(item,index) in prop.model.items">
          <div class="select-title" v-show="prop.model.isBranches.length||prop.model.type === 'dynamic'">
            {{'第'+(index+1)+ (prop.model.type === 'dynamic' ? '项':'级')}} <i class="el-icon-error"
                                                                            @click.prevent="removeSelect(index)"
                                                                            v-show="index > 0"></i>
          </div>
          <el-form-item label="类型" v-show="prop.model.isBranches.length||prop.model.type === 'dynamic'">
            <el-select v-model="item.type" placeholder="请选择这级类型" @change="selectChange(item)">
              <el-option v-for="(list,index) in typeData" :key="index" :label="list.name"
                         :value="list.value"></el-option>
            </el-select>
          </el-form-item>

          <el-form-item :prop="'items.' + index + '.label'" label="标题" :rules="prop.rules.label">
            <el-input v-model="item.label"></el-input>
          </el-form-item>

          <el-form-item :prop="'items.' + index + '.name'" label="标识ID"
                        v-show="prop.model.type !== 'title'"
                        :rules="prop.model.type === 'title' ? [] :prop.rules.name">
            <el-input v-model="item.name" readonly></el-input>
          </el-form-item>

          <el-form-item label="时间控件类型"
                        v-if="isEqual(prop.model.type,item.type,'datePicker')"
                        :prop="'items.' + index + '.timeType'"
                        :rules="prop.rules.timeType">
            <el-radio-group v-model="item.timeType">
              <el-radio label="date">日期</el-radio>
              <el-radio label="daterange">日期范围</el-radio>
              <el-radio label="datetime">时间日期</el-radio>
              <el-radio label="datetimerange">时间日期范围</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="获取数据项方式"
                        v-if="isEqual(prop.model.type,item.type,'radio','checkbox','select','treeSelect')"
                        :prop="'items.' + index + '.useMethod'" :rules="prop.rules.useMethod">
            <el-radio-group v-model="item.useMethod" size="small" @change="methodChange(item)">
              <el-radio label="dictionary">使用字典值</el-radio>
              <el-radio label="optionUrl" v-show="prop.model.type !== 'treeSelect'">接口链接</el-radio>
              <el-radio label="methodValue" v-show="prop.model.type !== 'treeSelect'">自定义格式</el-radio>
            </el-radio-group>
          </el-form-item>

          <el-form-item label="字典值名称" v-if="item.useMethod === 'dictionary'"
                        :prop="'items.' + index + '.dictionaryName'" :rules="prop.rules.dictionaryName">
            <el-input v-model="item.dictionaryName"></el-input>
          </el-form-item>

          <el-form-item label="接口地址" v-if="item.useMethod === 'optionUrl'"
                        :prop="item.useMethod === 'optionUrl' ? 'items.' + index + '.optionUrl' :''"
                        :rules="prop.rules.optionUrl">
            <el-input v-model="item.optionUrl"></el-input>
          </el-form-item>

          <el-form-item label="自定义值" v-if="item.useMethod === 'methodValue'"
                        :prop="item.useMethod === 'methodValue' ? 'items.' + index + '.methodValue' :''"
                        :rules="prop.rules.methodValue">
            <el-input type="textarea" v-model="item.methodValue" :rows="5"
                      placeholder="[{name: '第一项', label: 'cate1'},{name: '第二项', label: 'cate2'}]"></el-input>
          </el-form-item>

          <el-form-item label="排列" v-show="prop.model.type !== 'title'">
            <el-radio-group v-model="item.columnNumber">
              <el-radio-button label="1">一行一列</el-radio-button>
              <el-radio-button label="2">一行两列</el-radio-button>
              <el-radio-button label="3">一行三列</el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="上传内容" v-if="isEqual(prop.model.type,item.type,'upload')">
            <el-radio-group v-model="item.accept">
              <el-radio label="">所有</el-radio>
              <el-radio
                label="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
                Excel文档
              </el-radio>
              <el-radio label="image/*">图片</el-radio>
              <el-radio label="audio/*">音频</el-radio>
              <el-radio label="video/*">视频</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="上传个数" v-if="isEqual(prop.model.type,item.type,'upload')">
            <el-radio-group v-model="item.limit">
              <el-radio label="">无限</el-radio>
              <el-radio label="1">单个</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="验证" v-show="prop.model.type !== 'title'">
            <el-checkbox-group v-model="item.isRequired">
              <el-checkbox name="validateType" v-for="(list,index) in validateType" :key="index"
                           :label="list.value">{{list.name}}
              </el-checkbox>
            </el-checkbox-group>
          </el-form-item>
          <el-form-item label="验证规则"
                        v-show="prop.model.type === 'input' || prop.model.type === 'textarea'||item.type === 'input' || item.type === 'textarea'">
            <el-radio-group v-model="item.rulesMethod">
              <el-radio label="">无</el-radio>
              <el-radio label="url">链接</el-radio>
              <el-radio label="email">邮箱</el-radio>
              <el-radio label="number">数字</el-radio>
              <el-radio label="diy">自定规则</el-radio>
            </el-radio-group>
            <el-input v-model="item.rulesRegExp" class="inline-input" placeholder="请输入正则"
                      v-show="item.rulesMethod === 'diy'"></el-input>
          </el-form-item>
        </div>
        <el-button class="add-btn" type="primary" @click="addSelect(prop.model.type)"
                   v-show="prop.model.isBranches.length||prop.model.type === 'dynamic'">新增
        </el-button>
      </template>

    </xdh-curd>
  </div>
</template>

<style type="text/scss" lang="scss" scoped>
  .wrapper {
    height: 100%;
    .el-form {
      height: 100%;
      position: relative;
    }
  }

  .select-title {
    width: 100%;
    padding: 5px 80px;
    margin-bottom: 15px;
    border-bottom: 1px solid #ccc;
    font-size: 20px;
    color: #409EFF;
    i {
      color: #f00;
      cursor: pointer;
      float: right;
      margin-right: 100px;
    }
  }

  .form-box {
    padding: 20px;
  }

  .inline-input {
    width: 150px;
    margin-left: 20px;
    display: inline-block;
  }

  .add-btn {
    float: right;
    margin-right: 20px;
  }
</style>

<script>
  import XdhDialog from '../../widgets/xdh-dialog'
  import formItemList from '../../base/mixin/form-item-list'
  import formFormList from '../../base/mixin/form-form-list'
  import XdhCurd from '../../widgets/xdh-curd'
  import Sortable from 'sortablejs'
  import {clone} from '@/utils/convert'

  // 表单项类型
  const typeData = [
    {name: '标题', value: 'title'},
    {name: '输入框', value: 'input'},
    {name: '文本框', value: 'textarea'},
    {name: '单选框', value: 'radio'},
    {name: '复选框', value: 'checkbox'},
    {name: '时间控件', value: 'datePicker'},
    {name: '下拉框', value: 'select'},
    {name: '下拉树', value: 'treeSelect'},
    {name: '动态表单', value: 'dynamic'},
    {name: '上传控件', value: 'upload'},
    {name: '批量导入数据', value: 'import'}
  ]
  const validateType = [
    {name: '必填项', value: 'required'}
  ]
  export default {
    components: {
      XdhDialog,
      XdhCurd
    },
    mixins: [formItemList, formFormList],
    data() {
      const optionUrlRex = function (rule, value, callback) {
          let reg = /^\/\S*$/;
          if (!reg.test(value)) {
            callback(new Error('请输入正确的url,以斜杠开头和中间不能有空格'));
          } else {
            callback();
          }
        },
        valueRex = function (rule, value, callback) {
          try {
            let Fn = Function;
            new Fn('return' + value)();
            callback();
          } catch (e) {
            callback(new Error('请输入正确json格式'));
          }
        };
      return {
        isEdit: false,
        editIndex: null,
        sortable: null,
        typeData: typeData,
        validateType: validateType,
        isBranches: [
          {name: '级联下拉框', value: 'true'}
        ],
        mixin: formItemList,
        pager: false,
        isSortTable: false,
        pageSize: 10000,
        id: {formId: ''},
        dialogFormSize: '',
        form: {
          isBranches: [],
          type: '',
          formId: '',
          label: '',
          valuezd: 'f1',
          items: [{
            label: '',
            name: '',
            type: '',
            useMethod: '',
            dictionaryName: '',
            optionUrl: '',
            methodValue: '',
            timeType: '',
            columnNumber: 1,
            isRequired: [],
            rulesMethod: '',
            accept: '',
            limit: '',
            rulesRegExp: ''
          }]
        },
        formRules: {
          label: [{required: true, message: '请输入标题'}],
          type: [{required: true, message: '请选择类型'}],
          name: [{required: true, message: '请输入字段标识'}],
          timeType: [{required: true, message: '请选择类型'}],
          useMethod: [{required: true, message: '请选择类型'}],
          dictionaryName: [{required: true, message: '请选择类型'}],
          methodValue: [{required: true, validator: valueRex, trigger: 'blur'}],
          optionUrl: [{required: true, validator: optionUrlRex, trigger: 'blur'}]
        },
        formData: JSON.parse(window.localStorage.getItem('formData')) || []
      }
    },
    watch: {
      '$route': {
        immediate: true,
        handler(val) {
          if (val.query.formId) {
            this.id.formId = val.query.formId
            this.form.formId = val.query.formId
            this.$nextTick(() => {
              this.$refs.formItemList.reload()
            })
          }
        }
      }
    },
    computed: {},
    created() {
    },
    mounted() {
    },
    methods: {
      selectChange(prop) {
        let value,
          obj;
        if (prop.model && prop.model.type) {
          value = prop.model.type
          obj = prop.model.items[0]
          prop.model.isBranches = []
          this.isBranchesChange(prop.model.isBranches)
        } else {
          value = prop.type
          obj = prop
        }

        if (value === 'datePicker') {
          obj.useMethod = ''
        } else if (value === 'radio' || value === 'checkbox' || value === 'select' || value === 'treeSelect') {
          obj.timeType = ''
        } else {
          obj.useMethod = ''
          obj.timeType = ''
        }
      },
      isBranchesChange(val) {
        if (!val.length) {
          this.$refs.formItemList.$refs.dialogForm.currentModel.items.splice(1)
        }
      },
      generateOnlyId() {
        return `d_${Date.parse(new Date())}`
      },
      addSelect(type) {
        if (this.$refs.formItemList.$refs.dialogForm.currentModel.items.length < 3 || type === 'dynamic') {
          this.$refs.formItemList.$refs.dialogForm.currentModel.items.push({
            label: '',
            name: this.generateOnlyId(),
            useMethod: '',
            dictionaryName: '',
            optionUrl: '',
            methodValue: '',
            type: '',
            timeType: '',
            columnNumber: 1,
            isRequired: [],
            rulesMethod: '',
            accept: '',
            limit: '',
            rulesRegExp: ''
          })
        } else {
          this.$message({type: 'warning', message: '最多只能添加3级'});
        }
      },
      removeSelect(index) {
        if (index !== 0) {
          this.$refs.formItemList.$refs.dialogForm.currentModel.items.splice(index, 1)
        }
      },
      methodChange(item) {
        item.methodValue = null
        item.optionUrl = null
        item.dictionaryName = null
      },
      sortTableChange() {
        if (!this.sortable || this.isSortTable) {
          this.$nextTick(() => {
            const el = this.$el.querySelectorAll('.el-table__body-wrapper tbody')[0];
            this.sortable = Sortable.create(el, {
              disabled: false,
              onUpdate: evt => {
                // 拖动时sortTable改变了el，
                // sortable.js已经将dom结构变成拖拽后的样子，需要先改回来=。=
                evt.from.removeChild(evt.item)
                evt.from.insertBefore(evt.item, evt.from.childNodes[evt.oldIndex]);
                // 然后正常操作列表数据，通过数据的变化驱动dom结构再次变成拖拽后的样子
                // 手动转换data
                const targetRow = this.$refs.formItemList.vm.formItemList.list.splice(evt.oldIndex, 1)[0]
                this.$refs.formItemList.vm.formItemList.list.splice(evt.newIndex, 0, targetRow)
              }
            });
          })
        } else {
          // 开关控制是否拖拉
          this.sortable.options.disabled = !this.sortable.options.disabled
        }
      },
      handleDialogOpen(mode, currentModel) {
        if (mode === 'update') {
          this.$refs.formItemList.currentModel.items = JSON.parse(currentModel.items)
        } else if (mode === 'insert') {
          this.$refs.formItemList.currentModel.items[0].name = this.generateOnlyId()
          // 新增时增加f1-f40的序号
          for (let i = 1; i < 41; i++) {
            let valuezd = 'f' + i
            if (!this.$refs.formItemList.vm.formItemList.list.find(list => list.valuezd === valuezd)) {
              this.$refs.formItemList.currentModel.valuezd = valuezd
              return false
            }
          }
        }
      },
      insertHandler(model) {
        // 处理数据
        model.label = model.type === 'dynamic' || model.isBranches.length ? model.label : model.items[0].label
        model.items = JSON.stringify(model.items)
        return this.addFormItemList(model)
          .then(res => {
            this.$refs.formItemList.reload()
            return res;
          })
          .catch(err => {
            return Promise.reject(err)
          })
      },
      updateHandler(model) {
        // 处理数据
        model.label = model.type === 'dynamic' || model.isBranches.length ? model.label : model.items[0].label
        model.items = JSON.stringify(model.items)
        return this.updateFormItemList(model)
          .then(res => {
            this.$refs.formItemList.reload()
            return res;
          })
          .catch(err => {
            return Promise.reject(err)
          })
      },
      isEqual(prop, item, ...args) {
        return ([...args].includes(prop) && !item) || [...args].includes(item)
      },
      view() {
        window.open(`${window.location.pathname}#/customForm?formId=${this.id.formId}`)
      },
      saveSortTable() {
        let arr = [];
        this.$refs.formItemList.vm.formItemList.list.forEach(list => {
          arr.push(list.pkValue)
        })
        this.sortItemList({pkValue: this.id.formId, itemOrder: arr}).then(() => {
          this.$message({
            message: '顺序保存成功!',
            type: 'success'
          })
          this.isSortTable = false;
          this.sortTableChange();
        })
      },
      createHtml() {
        // 处理联动的数据结构 函数
        const organizeArr = (arrlist) => {
          return arrlist.reduceRight((right, left) => {
            right && (left.grade = right);
            return left;
          });
        }

        // 处理生成表单需要的数据格式
        const organizeObjects = (obj, val) => {
          val.type = val.type ? val.type : obj.type;
          if (obj.type === 'dynamic') {
            obj.name = obj.items[0].name
          }
          // 处理必填
          if (val.rulesRegExp) {
            val.rules = {
              required: val.isRequired && val.isRequired[0] === 'required',
              type: val.rulesMethod,
              validator: val.rulesRegExp,
              trigger: 'blur'
            };
          }
          if (val.isRequired[0] === 'required') {
            val.rules = {
              required: val.isRequired && val.isRequired[0] === 'required',
              type: val.type === 'checkbox' || val.type === 'treeSelect' || val.type === 'upload' ? 'array' : val.type === 'datePicker' ? 'date' : val.rulesMethod,
              validator: val.rulesRegExp,
              message: val.label + '为必填项'
            };
            if (val.type === 'upload') {
              val.rules.trigger = 'change'
            }
          }
          // 处理时间
          if (val.timeType === 'date' || val.timeType === 'datetime') {
            val.props = {
              type: val.timeType
            }
          } else if (val.timeType === 'daterange' || val.timeType === 'datetimerange') {
            val.props = {
              endPlaceholder: '结束日期',
              rangeSeparator: '至',
              startPlaceholder: '开始日期',
              type: val.timeType
            }
          }
          // 处理类型
          if (val.type === 'textarea') {
            val.props = {
              rows: 5,
              type: 'textarea'
            }
            obj.type = 'input';
          } else if (val.type === 'upload') {
            val.props = {
              limit: parseInt(val.limit),
              accept: val.accept
            }
          } else if (val.type === 'title') {
            val.props = {
              title: val.label
            }
          }
        }
        const arr = clone(this.$refs.formItemList.vm.formItemList.list);
        // const arr = [...this.$refs.formItemList.vm.formItemList.list];
        const newObj = arr.map(function (obj) {
          obj.items = JSON.parse(obj.items)
          obj.items.forEach(list => {
            organizeObjects(obj, list)
          })
          if (obj.type === 'dynamic') {
            obj.children = [];
            obj.children.push(obj.items)
            return Object.assign({}, obj)
          } else {
            return Object.assign({}, organizeArr(obj.items), obj)
          }
        });
        this.updateFormFormList({
          pkValue: this.id.formId,
          content: JSON.stringify(newObj),
          name: this.$router.currentRoute.query.formName
        }).then(() => {
          this.$message({
            message: '生成表单成功!',
            type: 'success'
          })
          // window.localStorage.setItem('formData', JSON.stringify(newObj))
        }).catch(err => {
          this.$message({
            message: err + '生成表单失败!',
            type: 'error'
          })
        })
      }
    }
  }
</script>
